home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 406_01 / disked25 / source / mylib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-13  |  21.0 KB  |  865 lines

  1. /* MYLIB.C  Generic Library Functions */
  2.  
  3. /* Copyright (c) Gregg Jennings 1989-1994 */
  4.  
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include <conio.h>
  8. #include <string.h>
  9. #include <dos.h>
  10.  
  11. #include "mylib.h"
  12.  
  13. #define _tohex(c)   ( (c<='9') ? (c-'0') : (c-'7') )
  14.  
  15. #define ischar(c)   ( c != 0 && c != 7 && c != 8 && c != 9 && c != 10 && \
  16.                       c != 13 && c != 27 && c != 255 )
  17.  
  18. /*
  19.    Convert two ASCII hex-valid chars to one hex number.
  20.    A '0' and a 'd' returns the value 0x0d.  The second
  21.    argument can be a '\r'.
  22.  
  23.    No checking for validity.
  24.  
  25.    ver 1.1 9/91    fixed ascii mask error, added _tohex() macro
  26.    ver 1.0 12/90
  27. */
  28. unsigned char hexbyte(register int a,register int b)
  29. {
  30.     a=toupper(a);
  31.     b=toupper(b);
  32.  
  33.     if (b=='\r') {      /* swap if '\r' */
  34.         b=a;
  35.         a='0';
  36.     }
  37.     return((unsigned char)((_tohex(a)*16)+_tohex(b)));
  38. }
  39. /*
  40.  * Display a number to the console with leading zeros or space
  41.  * and a certain length, and any base from 2 to 36.
  42.  *
  43.  * pn    print int number
  44.  * pln   print long number
  45.  *
  46.  *   Returns: number of digits.
  47.  *
  48.  *   ver 1.0 9/91     eliminated all but 2 divisions pln(), 3 in pn()
  49.  *   ver 0.1 12/90
  50.  */
  51.  
  52. int pn(unsigned int n, int base)
  53. {
  54. int r=1;
  55. int i;
  56.  
  57.     if (n/base)
  58.         r+=pn(n/base,base);
  59.     i=n%base;
  60.     conout((i>9) ? i+'A'-10 : i+'0');
  61.     return(r);
  62. }
  63.  
  64. int pln(unsigned long n, int base)
  65. {
  66. int r=1;
  67. long l;
  68. int i;
  69.  
  70.    if (((l=n/(long)base))>0)
  71.         r+=pln(l,base);
  72.     i=(int)(n%(long)base);
  73.     if (i>9)
  74.         conout(i+'A'-10);
  75.     else
  76.         conout(i+'0');
  77.     return(r);
  78. }
  79.  
  80. /*
  81.  * Display a number to the console with leading zeros or space
  82.  * and a certain length, and any base from 2 to 36.
  83.  *
  84.  * pnlz   print number leading zero
  85.  * pnls   print number leading space
  86.  * plnlz  print long number leading zero
  87.  * plnls  print long number leading space
  88.  *
  89.  *   ver 1.0   9/91
  90.  */
  91.  
  92. void pnlz(unsigned int n, unsigned int length, int base)
  93. {
  94. register int t;
  95.  
  96.     for (t=length-getlen(n,base);t>0;t--)
  97.         conout('0');
  98.     pn(n,base);
  99. }
  100.  
  101. void pnls(unsigned int n, unsigned int length, int base)
  102. {
  103. register int t;
  104.  
  105.     for (t=length-getlen(n,base);t>0;t--)
  106.         conout(' ');
  107.     pn(n,base);
  108. }
  109.  
  110. void plnlz(unsigned long n, unsigned int length, int base)
  111. {
  112. register int i;
  113.  
  114.     for (i=length-getlength(n,base);i>0;i--)
  115.         conout('0');
  116.     pln(n,base);
  117. }
  118.  
  119. void plnls(unsigned long n, unsigned int length, int base)
  120. {
  121. register int i;
  122.  
  123.     for (i=length-getlength(n,base);i>0;i--)
  124.         conout(' ');
  125.     pln(n,base);
  126. }
  127.  
  128. /*
  129.  * get the display length (number of digits) of a
  130.  * number, i.e. 100 dec returns 3, 64 hex (100 dec)
  131.  * returns 2
  132.  */
  133.  
  134. int getlen(register unsigned int n, register int base)
  135. {
  136. int j;
  137.  
  138.     for (j=1;n>=(unsigned int)base;n/=base,++j)
  139.         ;
  140.     return(j);
  141. }
  142. /*
  143.     Get length of number.
  144.     Pass: long number, int base (1 to 26).
  145.     Returns: the number of digits the number needs to be displayed.
  146.  
  147.     ver 0.1 12/90
  148.     ver 0.2 3/91    changed to long
  149. */
  150.  
  151. int getlength(unsigned long l, int base)
  152. {
  153. register int r;
  154.  
  155.     for (r=1;l>=(unsigned long)base;l/=(long)base,++r)
  156.         ;
  157.     return(r);
  158. }
  159.  
  160. /*
  161.     Convert a string containing escape sequences
  162.     to their correct values.
  163.  
  164.     Returns: the converted string's length.
  165.  
  166.     ver 1.1 9/91    changed \x to fixed 2 chars (\x0d not \xd)
  167.     ver 1.0 3/91
  168.     ver 0.1 12/90
  169. */
  170.  
  171. int convert(register char *a)
  172. {
  173. register char *s;
  174. int j;
  175.  
  176.     s=a;
  177.     for (j=0;*a!='\0';a++,j++) {
  178.         if (*a=='\\') {
  179.             switch (*++a) {
  180.             case 'x':
  181.                 *(s+j)=hexbyte(*(a+1),*(a+2));
  182.                 a+=2;
  183.                 break;
  184.             case 'a':
  185.                 *(s+j)='\a';
  186.                 break;
  187.             case 'b':
  188.                 *(s+j)='\b';
  189.                 break;
  190.             case 'f':
  191.                 *(s+j)='\f';
  192.                 break;
  193.             case 'n':
  194.                 *(s+j)='\n';
  195.                 break;
  196.             case 'r':
  197.                 *(s+j)='\r';
  198.                 break;
  199.             case 't':
  200.                 *(s+j)='\t';
  201.                 break;
  202.             case 'v':
  203.                 *(s+j)='\v';
  204.                 break;
  205.             case '0':
  206.                 *(s+j)='\0';
  207.                 break;
  208.             case '\\':
  209.                 *(s+j)='\\';
  210.                 break;
  211.             default:
  212.                 break;
  213.             }
  214.         }
  215.         else
  216.             *(s+j)=*a;
  217.     }
  218.     *(s+j)='\0';
  219.     a=s;
  220.     return(j);
  221. }
  222. /*
  223.     Display the current directory in a combination DIR /P /W
  224.     format.
  225.  
  226.     ver 0.3 9/91   call to lpd()
  227.     ver 0.2 3/91
  228. */
  229.  
  230. void dir(void)
  231. {
  232. int files=0;
  233. struct find_t file;
  234. long fsize = 0L;
  235. struct diskfree_t ds;
  236. long dsize;
  237. extern unsigned int disk;
  238. extern unsigned avail_clusters;
  239. extern unsigned secs_cluster;
  240. extern unsigned sec_size;
  241.  
  242.    send('\n');
  243.    if (_dos_findfirst("*.*",0x3f,&file)==0)
  244.    {
  245.       do
  246.       {
  247.          pname(file.name);
  248.          print("  ");
  249.          if (file.attrib&_A_SUBDIR)
  250.             print("  <DIR>");
  251.          else if (file.attrib&_A_VOLID)
  252.             print("  <VOL>");
  253.          else
  254.          {
  255.             plnls(file.size,7,10);
  256.             fsize+=file.size;
  257.          }
  258.          ++files;
  259.          print((files%3==0) ? "\n" : "   ");
  260.          if (files%60==0)
  261.             pause();
  262.       } while (_dos_findnext(&file)==0);    /* while being found*/
  263.    }
  264.    if (files==0)
  265.            print("no files");
  266.    send('\n');
  267.    if (avail_clusters==0)
  268.    {
  269.       _dos_getdiskfree(disk,&ds);
  270.       dsize = ((long)ds.avail_clusters*(long)ds.sectors_per_cluster*(long)ds.bytes_per_sector);
  271.    }
  272.    else
  273.       dsize = ((long)avail_clusters*(long)secs_cluster*(long)sec_size);
  274.    printf(" file space %ld, disk space %ld\n",fsize,dsize);
  275. }
  276.  
  277. /*
  278.     Displays the filename returned by _dos_findnext() in a nice
  279.     format.
  280.  
  281.     ver 0.2 3/91
  282. */
  283.  
  284. void pname(char *s)
  285. {
  286. register int i;
  287. register int j;
  288.  
  289.    i=0;
  290.    conout(' ');
  291.    while (s[i]!='.' && s[i]!='\0')
  292.       conout(s[i++]);
  293.    j= (s[i]!='\0') ? i+1 : i;
  294.    while (i++<8)
  295.       conout(' ');
  296.    if (s[j])
  297.       conout('.');
  298.    else
  299.       conout(' ');
  300.    while (i++<=11)
  301.       conout( (s[j]=='\0') ? ' ' : s[j++]);
  302. }
  303.  
  304. /*
  305.     Modified K&R index() for a non-null terminated string.
  306.  
  307.     ver 0.1 12/90
  308. */
  309.  
  310. search(unsigned char *s,unsigned char *t,unsigned int size,unsigned int len)
  311. {
  312. unsigned int i;
  313. register unsigned int j,k;
  314.  
  315.     if (size>len) {
  316.         size-=len;
  317.         for (i=0;i<=size;i++) {
  318.             for (j=i,k=0;k<len && s[j]==t[k];j++,k++)
  319.                 continue;
  320.             if (k==len)
  321.                 return(i);
  322.         }
  323.     }
  324.     return(-1);
  325. }
  326.  
  327. /* case-insensitive search 11-93 */
  328.  
  329. isearch(unsigned char *s,unsigned char *t,unsigned int size,unsigned int len)
  330. {
  331. unsigned int i;
  332. register unsigned int j,k;
  333.  
  334.    if (size > len)
  335.    {
  336.       size-=len;
  337.       for (i=0;i <= size;i++)
  338.       {
  339.          for (j=i,k=0;k<len && (s[j]==t[k] || toupper(s[j]) == toupper(t[k]));j++,k++)
  340.             continue;
  341.        if (k==len)
  342.           return(i);
  343.       }
  344.    }
  345.    return(-1);
  346. }
  347. /*
  348.    Display a string with a question mark and return TRUE if a 'y'
  349.    is found on console, else return FALSE.
  350.  
  351.    mode: 0  no mov/clr
  352.    (bit) 1  cursor back to "Yes/No "
  353.          2  cursor back to arg s
  354.          4  clreol if "Yes"
  355.  
  356.    ver 0.3 9/93  added cursor, clreol
  357.    ver 0.2 3/91
  358.    ver 0.1 12/91
  359. */
  360.  
  361. int getver(register char *s,int mode)
  362. {
  363. int c;
  364.  
  365.    if (mode&2)          /* mov arg */
  366.       savecursor();
  367.    print(s);
  368.    conout('?');
  369.    conout(' ');
  370.    if (mode&1)          /* mov yn */
  371.       savecursor();
  372.    c=input();
  373.    if (tolower(c)!='y')
  374.    {
  375.       print("No ");
  376.       c = 0;
  377.       if (mode)
  378.          restcursor();
  379.    }
  380.    else
  381.    {
  382.       print("Yes");
  383.       c = 1;
  384.       if (mode)
  385.          restcursor();
  386.       if (mode&4)
  387.          clreol();
  388.    }
  389.    return c;
  390. }
  391. /*
  392.     Get number from console by calling getstr() and sscanf().
  393.     Handles base of 10 or 16 only.
  394.  
  395.     Pass: long maximum number, pointer to number, int base (1 to 26).
  396.  
  397.     Returns: TRUE  (1)  if number okay
  398.          FALSE (0)  if no entry
  399.          ERROR (-1) if too big a number
  400.          ABORT (-2) on ESC or ^C
  401.  
  402.     Calls: getstr()
  403.  
  404.     ver 0.1 12/90
  405.     ver 1.0 2/91    pass pointer
  406. */
  407. int getnumber(unsigned long max, void *num, int base)
  408. {
  409. char tmpstr[11];    /* longest number is unsigned long of 10 digits */
  410. char format[4];     /* format string for sscanf() */
  411. int i;
  412. unsigned long l;
  413. long *pl=num;       /* make sure we have enough space */
  414.  
  415.    i=0;
  416.    format[i++]='%';
  417.    format[i++]='l';
  418.    (base==10) ? (format[i]='d') : (format[i]='x');
  419.    format[++i]='\0';
  420.    i=getstr(tmpstr,getlength(max,base),(base==10)?_DIGIT:_HEX);
  421.    if (i<0)
  422.    {
  423.       if (i==ERROR)
  424.          i=0;
  425.       return(i);
  426.    }
  427.    sscanf(tmpstr,format,&l);
  428.    if (l>max)
  429.       return(ERROR);
  430.    *pl=l;
  431.    return(TRUE);
  432. }
  433.  
  434. int getnum(unsigned int max, unsigned *num, int base)
  435. {
  436. char tmpstr[7];            /* longest number is unsigned 6 digits */
  437. char format[3];            /* format string for sscanf() */
  438. int i;
  439. unsigned int u;
  440. unsigned int *pu=num;      /* make sure we have enough space */
  441.  
  442.    i=0;
  443.    format[i++]='%';
  444.    (base==10) ? (format[i]='u') : (format[i]='x');
  445.    format[++i]='\0';
  446.    i=getstr(tmpstr,getlen(max,base),(base==10)?_DIGIT:_HEX);
  447.    if (i<0)
  448.    {
  449.       if (i==ERROR)
  450.          i=0;
  451.       return(i);
  452.    }
  453.    sscanf(tmpstr,format,&u);
  454.    if (u>max)
  455.       return(ERROR);
  456.    *pu=u;
  457.    return(TRUE);
  458. }
  459.  
  460. /*
  461.     Get a string from console, masking to hex or decimal
  462.     numbers only or punctuation, depending on the mask value,
  463.     with CP/M editing control keys.
  464.  
  465.     Pass: pointer to string, int max length, int mask.
  466.  
  467.     Returns:   -2 on ESC or ^C
  468.                -1 on no input ('\r')
  469.                -3 on no input (space or ',')
  470.  
  471.     Uses: put(), bdos(), send() and <ctype.h>.
  472.  
  473.     ver 1.0 9/93     added -3 return
  474.     ver 0.1 12/90
  475. */
  476.  
  477. int getstr(char *s,unsigned int len,int mask)
  478. {
  479. register unsigned int i;
  480. register int c;
  481.  
  482.    savecursor();
  483.    for (i=0;i<len;)
  484.    {
  485.       switch (c=input())
  486.       {
  487.          case 8:
  488.             if (i)
  489.             {
  490.                conout(c);
  491.                conout(' ');
  492.                conout(c);
  493.                --i;
  494.             }
  495.             break;
  496.          case 0x15:          /* ^U to delete */
  497.             if (i)
  498.             {
  499.                restcursor();
  500.                clreol();
  501.                i=0;
  502.             }
  503.             break;
  504.          case 0x1b:
  505.          case 3:              /* ESC to abort */
  506.             s[0]='\0';
  507.             return(ABORT);
  508.             break;
  509.          case '\r':           /* end of input */
  510.          case ' ':
  511.          case ',':
  512.             break;
  513.          default:
  514.             if (mask==_DIGIT && (!isdigit(c)))
  515.                continue;
  516.             if (mask==_HEX && (!isxdigit(c)))
  517.                continue;
  518.             conout(c);        /* save and echo numbers */
  519.             s[i++]=(char)c;
  520.             continue;
  521.             break;
  522.       }
  523.       if (c==' ' || c==',' || c=='\r')
  524.          break;
  525.    }
  526.    s[i]='\0';
  527.    if (!i)
  528.       return (c=='\r') ? ERROR : -3;
  529.    return(i);
  530. }
  531.  
  532. /*
  533.    Edit a buffer, in a debugger type format.  Asks for the starting
  534.    point of the editing.  Checks for end of buffer and wraps around.
  535.    Allows hex and ASCII substitutions, jumps to a buffer location, and
  536.    hex number fills.
  537.  
  538.    A complicated, horrible looking function but it works.
  539.  
  540.    Uses getnumber(), bdos(), hexbyte(), dispval() and <ctype.h>.
  541.  
  542.    GAJ  initial
  543.    GAJ  added ASCII subs
  544.    GAJ  1-8-89 added ^x
  545.    GAJ  1-9-89 added \c
  546.    GAJ  3-8-89 updated help
  547.    GAJ  12-8-90 cleaned up
  548. */
  549. change(register unsigned char *buffer,unsigned int bufend,int base)
  550. {
  551. unsigned int a;
  552. unsigned int b;
  553. int c;          /* chars gotten from the console */
  554. unsigned int n,i;       /* x = buffer index, n = getval, i = general purpose*/
  555. register unsigned int x;
  556. int inquote,ad;       /* for inputing a string */
  557. int l;
  558. char t[66];
  559.  
  560.     if (bufend<=0)
  561.         return(0);
  562.     n=0;
  563.     if (getnum(bufend,&n,base)==ABORT)
  564.         return(0);
  565.     ad=getlen(bufend,base);
  566.     x=n;
  567.     inquote=FALSE;
  568.     send('\n');
  569.     for (;;) {
  570.         c=buffer[x];    /* display address, byte, and ASCII */
  571.         dispval(x,ad,base,c);
  572.         if (!inquote)
  573.             a=input()&0xff;
  574.  
  575.         if (a=='\\') {      /* search */
  576.             conout(a);           /* echo */
  577.             a=input()&0xff;       /* get */
  578.             if (a=='^') {       /* control */
  579.                 conout(a);           /* echo */
  580.                 b=input()&0xff;       /* get */
  581.                 if (isalpha(b)) {       /* letter */
  582.                     a=toupper(b);       /* upper */
  583.                     conout(a);           /* echo */
  584.                     c=(a-'@');          /* convert */
  585.                 }
  586.                 else continue;  /* else redo */
  587.             }
  588.             else if (a=='\'') {     /* get ASCII */
  589.                 conout(a);
  590.                 b=input()&0xff;
  591.                 if (b>=' ') {        /* is okay? */
  592.                     conout(b);       /* echo */
  593.                     c=b;        /* set */
  594.                 }
  595.                 else continue;  /* else redo */
  596.             }
  597.             else if (isxdigit(a)) {
  598.                 conout(a);
  599.                 b=input()&0xff;       /* get second */
  600.                 if (isxdigit(b) || b=='\r') {
  601.                     if (b!='\r')
  602.                         conout(b);
  603.                     c=hexbyte(a,b); /* convert */
  604.                 }
  605.                 else continue;
  606.             }                   /* search loop */
  607.             i=x;                /* save place */
  608.             while (c!=(int)buffer[++x]) {
  609.                 if (x==bufend)      /* wrap at end */
  610.                     x=0;
  611.                 if (x==i)           /* stop */
  612.                     break;
  613.             }
  614.             continue;
  615.         }
  616.         else if (a=='\"') {     /* get string */
  617.             conout(a);
  618.             inquote=FALSE;      /* bool for continueing */
  619.             if ((l=getstr(t,63,_PUNCT))>0) {
  620.                 for (i=0;i<(unsigned)l;i++) {         /* copy string */
  621.                     buffer[x++]=t[i];
  622.                     if (x==bufend)      /* wrap around */
  623.                         x=0;
  624.                 }
  625.             }
  626.             else continue;
  627.             if (l==63)
  628.                 inquote=TRUE;
  629.             continue;
  630.         }
  631.         else if (a=='^') {           /* get control */
  632.             conout(a);
  633.             b=input()&0xff;
  634.             if (isalpha(b)) {
  635.                 b=toupper(b);
  636.                 conout(b);
  637.                 buffer[x]=(char)(b-'@');
  638.             }
  639.             else continue;
  640.         }
  641.         else if (a=='\'') {         /* get ASCII */
  642.             conout(a);
  643.             b=input()&0xff;
  644.             if (b>=' ') {        /* is okay? */
  645.                 conout(b);       /* yes, display and set */
  646.                 buffer[x]=(char)b;
  647.             }
  648.             else continue;
  649.         }
  650.         else if (a=='=') {          /* jump to addr */
  651.             conout(a);
  652.             if (getnum(bufend,&n,base)<1)
  653.                 continue;
  654.             if (n>bufend)
  655.                 continue;
  656.                 x=n;
  657.                 continue;
  658.         }
  659.         else if (a=='\r' || a==' ')       /* go to next */
  660.             ;
  661.         else if (a=='\t') {          /* goto 0000: */
  662.             x = 0;
  663.             continue;
  664.         }
  665.         else if (a=='.' || a==ESC)      /* exit */
  666.             break;
  667.         else if (a=='\b')  {         /* go to previous */
  668.             if (--x == 0xffff) {
  669.                 x=(bufend-1);   /* if end, wrap */
  670.                 send('\n');
  671.             }
  672.             continue;
  673.         }
  674.         else if (a=='/' || a=='?') {    /* dislpay help */
  675.             print("\n\n\txx     enter hex value xx");
  676.             print("\n\t'c     enter ASCII char c");
  677.             print("\n\t^c     enter control char c");
  678.             print("\n\t\"s     enter string s");
  679.             print("\n\tCR/SP  next location");
  680.             print("\n\tBS     previous location");
  681.             print("\n\tTAB    goto location 00");
  682.             print("\n\t=n     goto location n");
  683.             print("\n\t\\xx    goto hex value xx");
  684.             print("\n\t\\\'c    goto char c");
  685.             print("\n\t\\^c    goto control char c");
  686.             print("\n\t-x1,x2 write x1, x2 times");
  687.             print("\n\t+x1,x2 replace all x1, with x2");
  688.             print("\n\t.|ESC  end\n");
  689.             continue;
  690.         }
  691.         else if (a=='-') {          /* fill */
  692.             conout(a);
  693.             if (getnum(0xff,&a,16)<1)
  694.                 continue;
  695.             conout(',');
  696.             if (getnum(bufend,&b,16)<1) /* get second byte */
  697.                 continue;
  698.             n=x;            /* save position */
  699.             for (i=0;i<b;i++) {     /* all okay, fill it */
  700.                 buffer[x]=(char)a;
  701.                 if (++x==bufend) /* wrap around at end */
  702.                     x=0;
  703.             }
  704.                 x=n;          /* restore position */
  705.                 continue;
  706.         }
  707.         else if (a=='+') {          /* fill */
  708.             conout(a);
  709.             if (getnum(0xff,&a,16)<1) /* get first byte */
  710.                 continue;
  711.             conout(',');
  712.             if (getnum(0xff,&b,16)<1) /* get second byte */
  713.                 continue;
  714.             if (a==b)
  715.                 continue;
  716.             for (i=0;i<bufend;i++) {     /* all okay, fill it */
  717.                 if (buffer[i]==(unsigned char)a)
  718.                     buffer[i]=(unsigned char)b;
  719.             }
  720.                 continue;
  721.         }
  722.         else if (isxdigit(a)) {
  723.             conout(a);
  724.             b=input()&0xff;       /* get second */
  725.             if (isxdigit(b) || b=='\r') {
  726.                 if (b!='\r')
  727.                     conout(b);
  728.                 buffer[x]=hexbyte(a,b); /* convert */
  729.             }
  730.             else continue;
  731.         }
  732.         else continue;
  733.         if (++x==bufend) {     /* increment pointer, wrap if end */
  734.             x=0;
  735.             send('\n');
  736.         }
  737.     }
  738.     send('\n');
  739.     return(1);
  740. }
  741.  
  742. void dispval(int x, int len, int base, int c)
  743. {
  744.     send('\n');
  745.     pnlz(x,len,base);
  746.     conout(':');
  747.     conout(' ');
  748.     pnlz(c,2,16);
  749.     conout(' ');
  750.     if (isprint(c)) {
  751.         conout('\'');
  752.         conout(c);
  753.         conout('\'');
  754.     }
  755.     else if (iscntrl(c)) {
  756.         conout('^');
  757.         conout(c+'@');
  758.         conout(' ');
  759.     }
  760.     else
  761.         put(3,' ');
  762.     put(2,' ');
  763. }
  764.  
  765. /*
  766.    Display data in a HEX-ASCII format, starting at buf, ending at
  767.    bufend.  Returns the number of bytes displayed.  bufend _must_
  768.    be a multiple of 128
  769.  
  770.      unsigned char *buffer;  - array of data
  771.      unsigned int bfptr;     - index into array
  772.      unsigned int bufend;    - size of array
  773.      unsigned int len;       - number of bytes to display
  774.      int base;
  775. */
  776. int dump(unsigned char *buffer,unsigned int bfptr,unsigned int bufend,unsigned int len,int base)
  777. {
  778. register unsigned int c;
  779. unsigned int l,n;
  780. register int b;
  781.  
  782.     if (bfptr>bufend)
  783.         bfptr=0;
  784.     if (len>bufend)
  785.         len=bufend;
  786.     n=bfptr;
  787.     for (l=0;l<len;l+=16) {
  788.         send('\n');
  789.         pnlz(bfptr,getlen(bufend,base),base);
  790.         conout(':');
  791.         conout(' ');
  792.         for (b=0; b<16; b++) {  /* of 16 bytes each */
  793.             c=buffer[bfptr];
  794.             conout( ((c>>=4) > 9) ? (c+0x57) : (c+'0'));
  795.             c=buffer[bfptr];
  796.             conout( ((c&=0xf) > 9) ? (c+0x57) : (c+'0'));
  797.             conout(' ');
  798.             if (++bfptr==bufend) {
  799.                 bfptr=0;
  800.                 break;
  801.             }
  802.         }
  803.         for (b=0; b<16; b++) {  /* in hex and ascii */
  804.             c=buffer[n];
  805.             conout( (ischar(c)) ? (c) : ('.'));
  806.             if (++n==bufend) {
  807.                 n=0;
  808.                 if (l<(len-16))
  809.                     send('\n');
  810.                 break;
  811.             }
  812.         }
  813.     }
  814.     return(bfptr);
  815. }
  816. void pause(void)
  817. {
  818.     savecursor();
  819.     print("<more>");
  820.     conin();
  821.     restcursor();
  822.     clreol();
  823. }
  824. /*
  825.  *      Display sector contents to the screen in HEX/ASCII.
  826.  */
  827.  
  828. void dumpf(register unsigned char *buffer,int size, int base)
  829. {
  830. register int c;
  831. int i,j;
  832. int ptr;
  833.  
  834.    send('\n');
  835.    for (ptr=0,i=0;i<size;i+=24)
  836.    {
  837.       pnlz(i,3,base);
  838.       conout(':');
  839.       conout(' ');
  840.       for (j=1;j<=24;j++)
  841.       {
  842.          c=buffer[ptr];
  843.          conout( ((c>>=4) > 9) ? (c+0x57) : (c+'0'));
  844.          c=buffer[ptr];
  845.          conout( ((c&=0xf) > 9) ? (c+0x57) : (c+'0'));
  846.          if (++ptr>=size)
  847.          {
  848.             conout(' ');
  849.             j=9;
  850.             break;
  851.          }
  852.          if (j%8==0)
  853.             conout(' ');
  854.       }
  855.       ptr-=(j-1);
  856.       for (j=1;j<=24;j++)
  857.       {
  858.          c=buffer[ptr];
  859.          conout( (c<' ' || c>0xfe) ? ('.') : (c));
  860.          if (++ptr>=size)
  861.             break;
  862.       }
  863.    }
  864. }
  865.